package com.example.demo.aspect;

import com.example.demo.annotation.AutoLog;
import com.example.demo.util.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.UUID;


@Slf4j
@Aspect
@Component
public class AutoLogAspect {
    private static final ThreadLocal<String> traceIdHolder = new ThreadLocal<>();

    @Around("@annotation(com.example.demo.annotation.AutoLog)")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        // 生成请求唯一ID（也可支持从请求头中取）
        String traceId = UUID.randomUUID().toString().replace("-", "").substring(0, 12);
        traceIdHolder.set(traceId);
        // 基础信息准备
        long startTime = System.currentTimeMillis();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        AutoLog autoLog = method.getAnnotation(AutoLog.class);
        String methodName = signature.getDeclaringTypeName() + "." + method.getName();
        Object[] args = joinPoint.getArgs();

        // 请求上下文
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = IpUtils.getIpAddr(request);
        String url = request.getRequestURI();
        String httpMethod = request.getMethod();

        // 用户信息（你可以结合 SecurityUtils 或其他方式）
        String username = "用户名***";
        // 示例：SecurityUtils.getUsername()（需集成登录模块）

        log.info("[{}] >> 操作: {} - 方法: {}", traceId, autoLog.value(), methodName);
        log.info("[{}] >> 请求方式: {} {} - 请求IP: {} - 用户: {} - 参数: {}", traceId, httpMethod, url,ip,username, Arrays.toString(args));

        Object result = null;
        boolean success = true;
        try {
            result = joinPoint.proceed();
            return result;
        } catch (Throwable ex) {
            success = false;
            log.error("[{}] << 捕获异常: {} - {}",traceId, ex.getClass().getName(), ex.getMessage());
            throw ex;
        } finally {
            long duration = System.currentTimeMillis() - startTime;
            log.info("[{}] << 耗时: {} ms", traceId, duration);
            log.info("[{}] << 状态: {}", traceId, success ? "成功" : "失败");
            traceIdHolder.remove();
        }
    }
}

